﻿namespace maranov.SymlinkManager.FilesystemLinks
{
    /// <summary>
    /// Filesystem link.
    /// </summary>
    public abstract partial class Link : ILink
    {
        /// <summary>
        /// Filesystem link.
        /// </summary>
        /// <param name="name">Link name in a filesystem.</param>
        /// <param name="target">Links target in a filesystem.</param>
        public Link(string name, string target)
        {
            Name = new Location(name);
            Target = new Location(target);
        }

        public virtual ILocation Target
        {
            get;
            private set;
        }

        public virtual ILocation Name
        {
            get;
            private set;
        }

        public virtual bool Exists
        {
            get
            {
                return Name.Exists;
            }
        }

        public virtual LinkState State
        {
            get
            {
                LinkState state = LinkState.None;

                // Validate link location
                if (Name.Exists)
                    state |= LinkState.LinkExists;
                else
                    state &= ~LinkState.LinkExists;

                // Validate target location
                if (Target.Exists)
                    state |= LinkState.TargetExists;
                else
                    state &= ~LinkState.TargetExists;

                // Validate connection
                if (ValidateLinkConnection())
                    state |= LinkState.ConnectionExists;
                else
                    state &= ~LinkState.ConnectionExists;

                return state;
            }
        }

        public virtual bool IsValid
        {
            get
            {
                return ValidateLink();
            }
        }

        public abstract void Create();

        public abstract void Remove(bool force = false);

        /// <summary>
        /// Validates link's existence, its connection to the target
        /// and target's existence if it's required.
        /// </summary>
        /// <returns>True if the link is valid.</returns>
        protected abstract bool ValidateLink();

        /// <summary>
        /// Validates that source and target both lead to the same file.
        /// </summary>
        /// <returns>True if the file ID is the same.</returns>
        protected abstract bool ValidateLinkConnection();
    }
}
